From 70ea24b9e8be0f119ee9a51bb08e8b23d4ca0c10 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Wed, 14 May 2014 12:56:16 +0200 Subject: [PATCH] colorplane: Fully port to GtkGesture A GtkGestureDrag is used for color selection, removing also the need to track the pointer state in widget data. The GDK grab performed just to set the crosshair cursor has been replaced by a call to gdk_window_set_device_cursor(), which will be unset if the drag operation is finished, or cancelled due to the implicit grab being broken. --- gtk/gtkcolorplane.c | 187 +++++++++++++++++++++----------------------- 1 file changed, 87 insertions(+), 100 deletions(-) diff --git a/gtk/gtkcolorplane.c b/gtk/gtkcolorplane.c index 26467e9b87..0b232f72f5 100644 --- a/gtk/gtkcolorplane.c +++ b/gtk/gtkcolorplane.c @@ -19,6 +19,7 @@ #include "gtkcolorplaneprivate.h" +#include "gtkgesturedrag.h" #include "gtkgesturelongpress.h" #include "gtkaccessible.h" #include "gtkadjustment.h" @@ -32,8 +33,8 @@ struct _GtkColorPlanePrivate GtkAdjustment *v_adj; cairo_surface_t *surface; - gboolean in_drag; + GtkGesture *drag_gesture; GtkGesture *long_press_gesture; }; @@ -180,32 +181,27 @@ plane_configure (GtkWidget *widget, } static void -set_cross_grab (GtkWidget *widget, - GdkDevice *device, - guint32 time) +set_cross_cursor (GtkWidget *widget, + gboolean enabled) { - GdkCursor *cursor; - - cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (widget)), - GDK_CROSSHAIR); - gdk_device_grab (device, - gtk_widget_get_window (widget), - GDK_OWNERSHIP_NONE, - FALSE, - GDK_POINTER_MOTION_MASK - | GDK_POINTER_MOTION_HINT_MASK - | GDK_BUTTON_RELEASE_MASK, - cursor, - time); - g_object_unref (cursor); -} + GdkCursor *cursor = NULL; + GdkWindow *window; + GdkDevice *device; -static gboolean -plane_grab_broken (GtkWidget *widget, - GdkEventGrabBroken *event) -{ - GTK_COLOR_PLANE (widget)->priv->in_drag = FALSE; - return TRUE; + window = gtk_widget_get_window (widget); + device = gtk_gesture_get_device (GTK_COLOR_PLANE (widget)->priv->drag_gesture); + + if (!window || !device) + return; + + if (enabled) + cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (widget)), + GDK_CROSSHAIR); + + gdk_window_set_device_cursor (window, device, cursor); + + if (cursor) + g_object_unref (cursor); } static void @@ -237,64 +233,6 @@ update_color (GtkColorPlane *plane, gtk_widget_queue_draw (widget); } -static gboolean -plane_button_press (GtkWidget *widget, - GdkEventButton *event) -{ - GtkColorPlane *plane = GTK_COLOR_PLANE (widget); - - if (event->button == GDK_BUTTON_SECONDARY) - { - gboolean handled; - - g_signal_emit_by_name (widget, "popup-menu", &handled); - - return TRUE; - } - - if (plane->priv->in_drag || event->button != GDK_BUTTON_PRIMARY) - return FALSE; - - plane->priv->in_drag = TRUE; - set_cross_grab (widget, gdk_event_get_device ((GdkEvent*)event), event->time); - update_color (plane, event->x, event->y); - gtk_widget_grab_focus (widget); - - return TRUE; -} - -static gboolean -plane_button_release (GtkWidget *widget, - GdkEventButton *event) -{ - GtkColorPlane *plane = GTK_COLOR_PLANE (widget); - - if (!plane->priv->in_drag || event->button != GDK_BUTTON_PRIMARY) - return FALSE; - - plane->priv->in_drag = FALSE; - - update_color (plane, event->x, event->y); - gdk_device_ungrab (gdk_event_get_device ((GdkEvent *) event), event->time); - - return TRUE; -} - -static gboolean -plane_motion_notify (GtkWidget *widget, - GdkEventMotion *event) -{ - GtkColorPlane *plane = GTK_COLOR_PLANE (widget); - - if (!plane->priv->in_drag) - return FALSE; - - gdk_event_request_motions (event); - update_color (plane, event->x, event->y); - - return TRUE; -} - static void hold_action (GtkGestureLongPress *gesture, gdouble x, @@ -306,17 +244,6 @@ hold_action (GtkGestureLongPress *gesture, g_signal_emit_by_name (plane, "popup-menu", &handled); } -static gboolean -plane_touch (GtkWidget *widget, - GdkEventTouch *event) -{ - GtkColorPlane *plane = GTK_COLOR_PLANE (widget); - - update_color (plane, event->x, event->y); - - return TRUE; -} - static void sv_move (GtkColorPlane *plane, gdouble ds, @@ -403,6 +330,57 @@ plane_key_press (GtkWidget *widget, return TRUE; } +static void +plane_drag_gesture_begin (GtkGestureDrag *gesture, + gdouble start_x, + gdouble start_y, + GtkColorPlane *plane) +{ + guint button; + + button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)); + + if (button == GDK_BUTTON_SECONDARY) + { + gboolean handled; + + g_signal_emit_by_name (plane, "popup-menu", &handled); + } + + if (button != GDK_BUTTON_PRIMARY) + { + gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED); + return; + } + + set_cross_cursor (GTK_WIDGET (plane), TRUE); + update_color (plane, start_x, start_y); + gtk_widget_grab_focus (GTK_WIDGET (plane)); + gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED); +} + +static void +plane_drag_gesture_update (GtkGestureDrag *gesture, + gdouble offset_x, + gdouble offset_y, + GtkColorPlane *plane) +{ + gdouble start_x, start_y; + + gtk_gesture_drag_get_start_point (GTK_GESTURE_DRAG (gesture), + &start_x, &start_y); + update_color (plane, start_x + offset_x, start_y + offset_y); +} + +static void +plane_drag_gesture_end (GtkGestureDrag *gesture, + gdouble offset_x, + gdouble offset_y, + GtkColorPlane *plane) +{ + set_cross_cursor (GTK_WIDGET (plane), FALSE); +} + static void gtk_color_plane_init (GtkColorPlane *plane) { @@ -424,10 +402,21 @@ gtk_color_plane_init (GtkColorPlane *plane) atk_object_set_role (atk_obj, ATK_ROLE_COLOR_CHOOSER); } + plane->priv->drag_gesture = gtk_gesture_drag_new (GTK_WIDGET (plane)); + g_signal_connect (plane->priv->drag_gesture, "drag-begin", + G_CALLBACK (plane_drag_gesture_begin), plane); + g_signal_connect (plane->priv->drag_gesture, "drag-update", + G_CALLBACK (plane_drag_gesture_update), plane); + g_signal_connect (plane->priv->drag_gesture, "drag-end", + G_CALLBACK (plane_drag_gesture_end), plane); + gtk_gesture_attach (plane->priv->drag_gesture, GTK_PHASE_TARGET); + gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (plane->priv->drag_gesture), + FALSE); + plane->priv->long_press_gesture = gtk_gesture_long_press_new (GTK_WIDGET (plane)); g_signal_connect (plane->priv->long_press_gesture, "pressed", G_CALLBACK (hold_action), plane); - gtk_gesture_attach (plane->priv->long_press_gesture, GTK_PHASE_BUBBLE); + gtk_gesture_attach (plane->priv->long_press_gesture, GTK_PHASE_TARGET); } static void @@ -442,6 +431,9 @@ plane_finalize (GObject *object) g_clear_object (&plane->priv->s_adj); g_clear_object (&plane->priv->v_adj); + gtk_gesture_detach (plane->priv->drag_gesture); + g_clear_object (&plane->priv->drag_gesture); + gtk_gesture_detach (plane->priv->long_press_gesture); g_clear_object (&plane->priv->long_press_gesture); @@ -503,12 +495,7 @@ gtk_color_plane_class_init (GtkColorPlaneClass *class) widget_class->draw = plane_draw; widget_class->configure_event = plane_configure; - widget_class->button_press_event = plane_button_press; - widget_class->button_release_event = plane_button_release; - widget_class->motion_notify_event = plane_motion_notify; - widget_class->grab_broken_event = plane_grab_broken; widget_class->key_press_event = plane_key_press; - widget_class->touch_event = plane_touch; g_object_class_install_property (object_class, PROP_H_ADJUSTMENT, -- 2.30.2